/**
 * @file Application.h
 * @brief CLink application main class
 *
 * This file contains the definition of the Application class which serves as the
 * main entry point for the CLink server application. It handles initialization,
 * configuration and lifecycle management of the application.
 */

#pragma once

#include <Poco/Util/ServerApplication.h>
#include <Poco/Net/HTTPServer.h>
#include <Poco/Net/HTTPServerParams.h>
#include <Poco/Net/ServerSocket.h>
#include <memory>
#include <string>

#include "../Server/Server.h"
#include "../CLink_Export.h"

namespace CLink
{
namespace App
{

/**
    * @class Application
    * @brief Main application class inheriting from Poco::Util::ServerApplication
    *
    * This class provides the core functionality for the CLink server application,
    * including:
    * - Application initialization and configuration
    * - Directory path management
    * - HTTP server setup
    * - Logging and database initialization
    */
class CLINK_CLASS Application : public Poco::Util::ServerApplication
{
public:
    /**
        * @brief Get the application version
        * @return const std::string& Application version string
        */
    const std::string &getVersion() const { return _version; }

    /**
        * @brief Get the application name
        * @return const std::string& Application name string
        */
    const std::string &getAppName() const { return _appName; }

    /**
        * @brief Get the application root directory
        * @return const std::string& Application root directory path
        */
    const std::string &getRootDir() const { return _rootDir; }

    /**
        * @brief Get the configuration directory path
        * @return std::string Full path to configuration directory
        */
    std::string getConfigDir() const;

    /**
        * @brief Get the log directory path
        * @return std::string Full path to log directory
        */
    std::string getLogDir() const;

    /**
        * @brief Get the data directory path
        * @return std::string Full path to data directory
        */
    std::string getDataDir() const;

    /**
        * @brief Get the temporary directory path
        * @return std::string Full path to temporary directory
        */
    std::string getTempDir() const;

    /**
        * @brief Get the static files directory path
        * @return std::string Full path to static files directory
        */
    std::string getStaticDir() const;

    /**
        * @brief Get the upload directory path
        * @return std::string Full path to upload directory
        */
    std::string getUploadDir() const;

    /**
        * @brief Get the Router pointer
        * @return const Router pointer
		*/
    CLink::Router::Router* getRouter();

    /**
        * @brief Add a route registration callback function
        * @param callback Function that will be called to register routes with the router
        */
	void addRegister(const std::function<void(CLink::Router::Router*)>& callback);

    /**
        * @brief Register routes using a template class
        * @tparam T Class type that implements operator() for route registration
        */
    template<typename T>
    void registerRoute()
    {
        addRegister(T());
    }

protected:
    /**
        * @brief Initialize the application
        * @param self Reference to the application instance
        */
    void initialize(Poco::Util::Application &self) override;

    /**
        * @brief Uninitialize the application
        */
    void uninitialize() override;

    /**
        * @brief Define application command line options
        * @param options OptionSet to populate with options
        */
    void defineOptions(Poco::Util::OptionSet &options) override;

    /**
        * @brief Handle a command line option
        * @param name Option name
        * @param value Option value
        */
    void handleOption(const std::string &name, const std::string &value) override;

    /**
        * @brief Main application entry point
        * @param args Command line arguments
        * @return int Application exit code
        */
    int main(const std::vector<std::string> &args) override;

private:
    /**
        * @brief Initialize application logging system
        */
    void initializeLogging();

    /**
        * @brief Initialize application configuration
        */
    void initializeConfig();

    /**
        * @brief Initialize application database
        */
    void initializeDatabase();

    /**
        * @brief Initialize HTTP server
        */
    void initializeHttpServer();

    /**
        * @brief Register HTTP routes
        */
    void registerRoutes();

    /**
        * @brief Create required application directories
        */
    void createDirectories();

    /**
        * @brief Display help information
        */
    void displayHelp();

    /**
        * @brief Display version information
        */
    void displayVersion();

    /**
     * @brief Application version string
     */
    std::string _version;
    
    /**
     * @brief Application name
     */
    std::string _appName;
    
    /**
     * @brief Root directory path of the application
     */
    std::string _rootDir;
    
    /**
     * @brief Path to the configuration file
     */
    std::string _configFile;
    
    /**
     * @brief Flag indicating if help information was requested
     */
    bool _helpRequested;
    
    /**
     * @brief Flag indicating if version information was requested
     */
    bool _versionRequested;

    /**
     * @brief Collection of callback functions for route registration
     */
	std::list<std::function<void(CLink::Router::Router*)>> _registerCallbacks;
    
    /**
     * @brief HTTP server instance that handles incoming requests
     */
    std::shared_ptr<CLink::Server::Server> _httpServer;

    /**
     * @brief Pointer to the router used for handling HTTP routes
	 */
    CLink::Db::DatabaseManager::Ptr _databaseManager;
};
}
}